package com.tomorrowbbs.aspect;

import com.tomorrowbbs.annotation.GlobalInterceptor;
import com.tomorrowbbs.annotation.VerifyParam;
import com.tomorrowbbs.domain.constants.Constants;
import com.tomorrowbbs.domain.enums.ResponseCodeEnum;
import com.tomorrowbbs.exception.BusinessException;
import com.tomorrowbbs.utils.StringTools;
import com.tomorrowbbs.utils.VerifyUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Component
@Aspect
public class OperactionAspect {

    private static final Logger logger = LoggerFactory.getLogger(OperactionAspect.class);
    private static final String[] TYPE_BASE = {"java.lang.String", "java.lang.Integer", "java.lang.Long"};

    @Pointcut("@annotation(com.tomorrowbbs.annotation.GlobalInterceptor)")
    private void requestInterceptor() {
    }

    @Around("requestInterceptor()")
    public Object InterceptorDo(ProceedingJoinPoint point) {
        try {
            // 获取当前被拦截方法的目标对象
            Object target = point.getTarget();
            // 获取当前被拦截方法的参数列表
            Object[] arguments = point.getArgs();
            // 获取当前被拦截方法的方法名
            String methodName = point.getSignature().getName();
            // 获取当前被拦截方法的参数类型数组
            Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
            // 通过反射获取目标对象中的方法对象
            Method method = target.getClass().getMethod(methodName, parameterTypes);
            // 获取方法上的 @GlobalInterceptor 注解
            GlobalInterceptor globalInterceptor = method.getAnnotation(GlobalInterceptor.class);
            // 如果方法上没有 @GlobalInterceptor 注解，则直接返回 null
            if (globalInterceptor == null) {
                return null;
            }
            //校验登录
            if (globalInterceptor.checkLogin()) {
                checkLogin();
            }
            //校验参数
            if (globalInterceptor.checkParams()) {
                ValidateParams(method, arguments);
            }
            Object pointResult = point.proceed();
            return pointResult;
        } catch (BusinessException e) {
            logger.error("全局拦截器异常", e);
            throw e;
        } catch (Exception e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }

    /*
    * 校验登录*/
    private void checkLogin() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpSession session = request.getSession();
        Object obj = session.getAttribute(Constants.SESSION_KEY);
        if(obj == null){
            throw new BusinessException(ResponseCodeEnum.CODE_901);
        }
    }

/*校验参数*/
    public void ValidateParams(Method method, Object[] arguments) {
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Object value = arguments[i];

            VerifyParam verifyParam = parameter.getAnnotation(VerifyParam.class);
            if (verifyParam == null) {
                continue;
            }
            if (ArrayUtils.contains(TYPE_BASE, parameter.getParameterizedType().getTypeName())) {
                checkValue(value, verifyParam);
            }

        }
    }

    private void checkObjValue(Parameter parameter, Object value) {

    }

    private void checkValue(Object value, VerifyParam verifyParam) {
        Boolean isEmpty = value == null || StringTools.isEmpty(value.toString());
        Integer length = value == null ? 0 : value.toString().length();
        /**
         * 校验空
         */
        if (isEmpty && verifyParam.required()) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        //校验长度
        if (!isEmpty && (verifyParam.max() != -1 && verifyParam.max() < length || verifyParam.min() != -1 && verifyParam.min() > length)) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        //校验正则
        if (!isEmpty && !StringTools.isEmpty(verifyParam.regex().getRegex()) && !VerifyUtils.verfiy(verifyParam.regex(), String.valueOf(value))) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
    }

}










